package com.mata.worktime.service.statistics.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mata.worktime.entity.user.Role;
import com.mata.worktime.entity.work.Member;
import com.mata.worktime.entity.work.Project;
import com.mata.worktime.service.user.RoleService;
import com.mata.worktime.service.work.MemberService;
import com.mata.worktime.service.work.ProjectService;
import com.mata.worktime.vo.statistics.ProjectDetailVO;
import com.mata.worktime.vo.statistics.ProjectStatisicsVO;
import com.mata.worktime.vo.statistics.UserDetailVO;
import com.mata.worktime.vo.statistics.UserStatisicsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mata.worktime.dao.statistics.StatisticsMapper;
import com.mata.worktime.dto.PageParamDTO;
import com.mata.worktime.dto.ProjectStatisticsParamDTO;
import com.mata.worktime.dto.UserStatisticsParamDTO;
import com.mata.worktime.entity.BaseEntity;
import com.mata.worktime.entity.user.Dept;
import com.mata.worktime.entity.user.Post;
import com.mata.worktime.entity.user.User;
import com.mata.worktime.service.statistics.StatisticsService;
import com.mata.worktime.service.user.DeptService;
import com.mata.worktime.service.user.PostService;
import com.mata.worktime.service.user.UserService;
import com.mata.worktime.util.DateUtils;
import com.mata.worktime.util.security.ShiroUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.mata.worktime.util.security.ShiroUtils.getUserId;


/**
 * @author earthchen
 * @date 2018/10/19
 **/
@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private StatisticsMapper statisticsMapper;

    @Autowired
    private PostService postMapper;

    @Autowired
    private UserService userMapper;

    @Autowired
    private DeptService deptMapper;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MemberService memberService;

    @Override
    public IPage<ProjectStatisicsVO> projectStatistics(ProjectStatisticsParamDTO dto,
                                                       PageParamDTO pageParamDTO) {
        Page<ProjectStatisicsVO> page = new Page<>(pageParamDTO.getPage(), pageParamDTO.getSize());
        return statisticsMapper.projectStatistics(page, dto);
    }

    @Override
    public List<ProjectStatisicsVO> projectStatistics(ProjectStatisticsParamDTO dto) {
        return statisticsMapper.projectStatistics(dto);
    }

    @Override
    public Map dailyStatistics(ProjectStatisticsParamDTO dto) {
        List<String> dateLists = new ArrayList<>();
        dateLists.clear();
        // 获取开始时间 与 结束时间 之间的日期
        dateLists.addAll(DateUtils.getDays(DateUtils.dateToStr(dto.getStartDate()), DateUtils.dateToStr(dto.getEndDate())));
        dto.setDateLists(dateLists);
        return statisticsMapper.dailyStatistics(dto);
    }

    @Override
    public IPage<UserStatisicsVO> userStatistics(UserStatisticsParamDTO dto,
                                                 PageParamDTO pageParamDTO) {
        Double shouldHour =
                7.5 * (DateUtils.getDayBetween(dto.getStartDate(), dto.getEndDate()) + 1 -
                        dto.getNum());
        dto.setShouldHour(shouldHour);
        //如果是经理或者管理员则查看自己部门下的员工工时

        int isLeader = 0;
        List<Role> roles = roleService.selectRolesByUserId(getUserId());
        for (Role role : roles) {
            if (role.isFlag()) {
                if (role.getRoleName().equals("项目经理")) {
                    isLeader += 1;
                }
                if (role.getRoleName().equals("部门经理")) {
                    isLeader += 2;
                }
                if (role.getRoleName().equals("管理员")) {
                    isLeader += 4;
                }
            }
        }
        if (isLeader == 1) {
            List<String> userIdList = new ArrayList<>();
            List<Long> projectIds = new ArrayList<>();
            List<Project> projects = projectService.list(new QueryWrapper<Project>().eq("manager", getUserId()));
            for (Project project : projects) {
                projectIds.add(project.getId());
            }
            List<Member> members = memberService.list(new QueryWrapper<Member>()
                    .in("pro_id", projectIds)
                    .select("user_id", "user_name", "pro_id", "join_time"));
            for (Member member : members) {
                userIdList.add(member.getUserId());
            }
            dto.setUserIds(userIdList);
        }

        if (isLeader == 2) {
            // 保存当前部门层级下所有用户信息
            List<User> deptUserList = new ArrayList<>();
            String deptId = ShiroUtils.getUser().getDeptId();
            getDeptUser(deptId, deptUserList);
            // 所有用户的id
            List<String> userIdList = deptUserList.stream().map(User::getId).collect(
                    Collectors.toList());
            dto.setUserIds(userIdList);
        }

        if (isLeader == 3) {
            List<String> userIdList = new ArrayList<>();
            List<Long> projectIds = new ArrayList<>();
            List<Project> projects = projectService.list(new QueryWrapper<Project>().eq("manager", getUserId()));
            for (Project project : projects) {
                projectIds.add(project.getId());
            }
            List<Member> members = memberService.list(new QueryWrapper<Member>()
                    .in("pro_id", projectIds)
                    .select("user_id", "user_name", "pro_id", "join_time"));
            for (Member member : members) {
                userIdList.add(member.getUserId());
            }

            // 保存当前部门层级下所有用户信息
            List<User> deptUserList = new ArrayList<>();
            String deptId = ShiroUtils.getUser().getDeptId();
            getDeptUser(deptId, deptUserList);
            // 所有用户的id
            userIdList.addAll(deptUserList.stream().map(User::getId).collect(
                    Collectors.toList()));
            dto.setUserIds(userIdList.stream().distinct().collect(Collectors.toList()));
        }


        Page<UserStatisicsVO> page = new Page<>(pageParamDTO.getPage(), pageParamDTO.getSize());
        IPage<UserStatisicsVO> userStatisicsVOS = statisticsMapper.userStatistics(page, dto);
        userStatisicsVOS.getRecords().forEach(u -> {
            // 计算应有工时
            u.setShouldHour(
                    7.5 * (DateUtils.getDayBetween(dto.getStartDate(), dto.getEndDate()) + 1 -
                            dto.getNum()));
        });
        return userStatisicsVOS;
    }

    @Override
    public List<UserStatisicsVO> userStatistics(UserStatisticsParamDTO dto) {
        List<UserStatisicsVO> userStatisicsVOS = statisticsMapper.userStatistics(dto);
        filter(userStatisicsVOS, dto);
        return userStatisicsVOS;
    }

    /**
     * 递归获取当前层级下所有用户的列表
     *
     * @param deptId       当前部门id
     * @param deptUserList 部门层级下的用户列表
     */
    private void getDeptUser(String deptId, List<User> deptUserList) {
        List<User> users = userMapper.list(new QueryWrapper<User>()
                .eq(deptId != null, "dept_id", deptId));
        if (users.isEmpty()) {
            return;
        }
        // 加入用户列表
        deptUserList.addAll(users);
        List<Dept> childDept = deptMapper.getChildrenDept(deptId);
        Set<Long> deptIdList = childDept.stream().map(BaseEntity::getId).collect(
                Collectors.toSet());

        for (Long id : deptIdList) {
            getDeptUser(id.toString(), deptUserList);
        }
    }

    /**
     * 过滤
     *
     * @param userStatisicsVOS
     * @param dto
     */
    private void filter(List<UserStatisicsVO> userStatisicsVOS, UserStatisticsParamDTO dto) {
        userStatisicsVOS.forEach(u -> {
            // 计算应有工时
            u.setShouldHour(
                    7.5 * (DateUtils.getDayBetween(dto.getStartDate(), dto.getEndDate()) + 1 -
                            dto.getNum()));
        });

        // 判断状态过滤是否异常
        if ("0".equals(dto.getStatus())) {
            userStatisicsVOS = userStatisicsVOS.stream().filter(
                    u -> u.getShouldHour().equals(u.getWorkhour())).collect(Collectors.toList());
        } else if ("1".equals(dto.getStatus())) {
            userStatisicsVOS = userStatisicsVOS.stream().filter(
                    u -> u.getShouldHour() > u.getWorkhour()).collect(Collectors.toList());
        }
    }

    @Override
    public IPage<UserDetailVO> userDetail(UserStatisticsParamDTO dto, PageParamDTO pageParamDTO) {
        Page<UserDetailVO> page = new Page<>(pageParamDTO.getPage(), pageParamDTO.getSize());
        return statisticsMapper.userDetail(page, dto);
    }

    @Override
    public IPage<ProjectDetailVO> projectDetail(ProjectStatisticsParamDTO dto,
                                                PageParamDTO pageParamDTO) {
        Page<ProjectDetailVO> page = new Page<>(pageParamDTO.getPage(), pageParamDTO.getSize());
        return statisticsMapper.projectDetail(page, dto);
    }
}
